package projeto.lp2.grupo6.testes;

import java.util.ArrayList;
import java.util.List;
import org.junit.*;
import projeto.lp2.grupo6.logica.Estabelecimento;
import projeto.lp2.grupo6.logica.RecomendacaoPersonalizada;
import projeto.lp2.grupo6.logica.TipoDeAlmocoServido;
import projeto.lp2.grupo6.logica.Usuario;

/**
 * Aluno: 
 *      Guilherme Monteiro
 *      Italo Guedes
 *      Tiago Leite
 * 
 * @author guilhermemg
 * @author tiagoln
 * @author italogas
 *
 */
public class RecomendacaoPersonalizadaTest {
     RecomendacaoPersonalizada recPer;

    List<Usuario> listaUsuarios1;
    List<Usuario> listaUsuarios2;

    Usuario ux;
    Usuario uy;
    Usuario uz;
    Usuario uw;
    Usuario u1;
    Usuario u2;
    Usuario u3;
    Usuario u4;

    Estabelecimento e1;
    Estabelecimento e2;
    Estabelecimento e3;
    Estabelecimento e4;
    Estabelecimento e5;

    List<TipoDeAlmocoServido> listaTipos1 = new ArrayList<TipoDeAlmocoServido>();
    List<TipoDeAlmocoServido> listaTipos2 = new ArrayList<TipoDeAlmocoServido>();
    List<TipoDeAlmocoServido> listaTipos3 = new ArrayList<TipoDeAlmocoServido>();

    @Before
    public void setup() {
        listaUsuarios1 = new ArrayList<Usuario>();
        listaUsuarios2 = new ArrayList<Usuario>();
        try {
            ux = new Usuario("Nome1");
            uy = new Usuario("Nome2");
            uz = new Usuario("Nome3");
            uw = new Usuario("Nome4");
            u1 = new Usuario("Nome5");
            u2 = new Usuario("Nome6");
            u3 = new Usuario("Nome7");
            u4 = new Usuario("Nome8");

            e1 = new Estabelecimento("nomeEstab1", "rua1", TipoDeAlmocoServido.A_LA_CARTE);
            e2 = new Estabelecimento("nomeEstab2", "rua2", TipoDeAlmocoServido.SELF_SERVICE);
            e3 = new Estabelecimento("nomeEstab3", "rua3", TipoDeAlmocoServido.PRATO_FEITO);
            e4 = new Estabelecimento("nomeEstab4", "rua4", TipoDeAlmocoServido.PRATO_FEITO);
            e5 = new Estabelecimento("nomeEstab5", "rua5", TipoDeAlmocoServido.PRATO_FEITO);

            ux.adicionaOpiniao(e1, 0);
            ux.adicionaOpiniao(e2, 3);
            ux.adicionaOpiniao(e3, -2);
            ux.adicionaOpiniao(e4, 2);
            ux.adicionaOpiniao(e5, -2);

            uy.adicionaOpiniao(e1, 4);
            uy.adicionaOpiniao(e2, 5);
            uy.adicionaOpiniao(e3, 1);
            uy.adicionaOpiniao(e4, 0);
            uy.adicionaOpiniao(e5, -5);

            uz.adicionaOpiniao(e1, 2);
            uz.adicionaOpiniao(e2, 0);
            uz.adicionaOpiniao(e3, -1);
            uz.adicionaOpiniao(e4, -4);
            uz.adicionaOpiniao(e5, -5);

            uw.adicionaOpiniao(e1, -2);
            uw.adicionaOpiniao(e2, 0);
            uw.adicionaOpiniao(e3, 0);
            uw.adicionaOpiniao(e4, 0);
            uw.adicionaOpiniao(e5, -3);
            
            u1.adicionaOpiniao(e1, 2);
            u1.adicionaOpiniao(e2, -2);
            u1.adicionaOpiniao(e3, 4);
            
            u2.adicionaOpiniao(e1, 0);
            u2.adicionaOpiniao(e2, 0);
            u2.adicionaOpiniao(e3, 0);
            
            u3.adicionaOpiniao(e1, 0);
            u3.adicionaOpiniao(e2, -3);
            u3.adicionaOpiniao(e3, 5);
            
            u4.adicionaOpiniao(e1, 0);
            u4.adicionaOpiniao(e2, -3);
            u4.adicionaOpiniao(e3, 5);

            listaTipos1.add(TipoDeAlmocoServido.A_LA_CARTE);
            listaTipos1.add(TipoDeAlmocoServido.SELF_SERVICE);

            listaTipos2.add(TipoDeAlmocoServido.PRATO_FEITO);

            listaTipos3.add(TipoDeAlmocoServido.A_LA_CARTE);
            listaTipos3.add(TipoDeAlmocoServido.PRATO_FEITO);
            listaTipos3.add(TipoDeAlmocoServido.SELF_SERVICE);
            
            listaUsuarios1.add(ux);
            listaUsuarios1.add(uy);
            listaUsuarios1.add(uz);
            listaUsuarios1.add(uw);
            
            listaUsuarios2.add(u1);
            listaUsuarios2.add(u2);
            listaUsuarios2.add(u3);
            listaUsuarios2.add(u4);

        }
        catch(Exception e) {
            Assert.fail("Nao esperava erro em construir objetos: " + e.getMessage());
        }
    }

    @Test
    public void testaConstrutor() {
        try {
            recPer = new RecomendacaoPersonalizada(listaUsuarios1, new Usuario("nome"));
        }
        catch(Exception e) {
            Assert.fail("Nao esperava erro em construtor: " + e.getMessage());
        }
        try {
	    	List<Usuario> listaUsuarios1P = new ArrayList<Usuario>();
	    	listaUsuarios1P.add(new Usuario("Nome1"));
	    	recPer = new RecomendacaoPersonalizada(listaUsuarios1P, new Usuario("nome2"));
    	}
    	catch(Exception e) {
    		Assert.fail("Nao esperava erro em construtor de RecomendacaoPersonalizada");
    	}
    	try {
	    	List<Usuario> listaUsuarios1P = new ArrayList<Usuario>();
	    	listaUsuarios1P.add(new Usuario("Nome1"));
	    	listaUsuarios1P.add(null);
	    	recPer = new RecomendacaoPersonalizada(listaUsuarios1P, new Usuario("nome2"));
    	}
    	catch(Exception e) {
    		Assert.assertEquals(e.getMessage(), "Erro em usuario nulo na lista de usuarios");
    	}
    }
    @Test(expected=Exception.class)
    public void testaConstrutor2() throws Exception {
    	recPer = new RecomendacaoPersonalizada(null, null);
    }
    
    @Test(expected=Exception.class)
    public void testaConstrutor3() throws Exception {
    	recPer = new RecomendacaoPersonalizada(new ArrayList<Usuario>(), null);
    }
    
    @Test(expected=Exception.class)
    public void testaConstrutor4() throws Exception {
    	List<Usuario> listaUsuarios1P = new ArrayList<Usuario>();
    	listaUsuarios1P.add(new Usuario("Nome1"));
    	recPer = new RecomendacaoPersonalizada(listaUsuarios1P, null);
    }
    
    @Test
    public void testaGetRecomendacao() {
        try {
            recPer = new RecomendacaoPersonalizada(listaUsuarios1, new Usuario("nome"));
        } catch (Exception ex) {
            Assert.fail("Nao esperava erro em construir objetos: " + ex.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, ux);
            recPer.getRecomendacao(0, listaTipos3, "");
        } catch(Exception e){
                Assert.assertEquals("Erro em quantidade de itens nula", e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, ux);
            recPer.getRecomendacao(-1, listaTipos3, "");
        } catch(Exception e){
                Assert.assertEquals("Erro em quantidade de itens negativa", e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, ux);
            recPer.getRecomendacao(2, null, "");
        } catch(Exception e){
                Assert.assertEquals("Erro em lista de tipos de almoco servidos nula", e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, ux);
            recPer.getRecomendacao(3, listaTipos3, null);
        } catch(Exception e){
                Assert.assertEquals("Erro em palavra-chave nula", e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, ux);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e1);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos3, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 1 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uy);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e4);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos3, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 2 de getRecomendacao" + e.getMessage());
        }
       
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uz);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e2);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos3, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 3 de getRecomendacao" + e.getMessage());
        }
         
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uw);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e2);
            listaEstabelecimentosP.add(e4);
            listaEstabelecimentosP.add(e3);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos3, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 4 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, ux);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos2, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 5 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uy);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e4);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos2, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 6 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uz);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos2, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 7 de getRecomendacao" + e.getMessage());
        }
         
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uw);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e4);
            listaEstabelecimentosP.add(e3);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos2, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 8 de getRecomendacao" + e.getMessage());
        }
         
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, ux);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e1);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos1, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 9 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uy);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos1, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 10 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uz);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e2);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos1, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 11 de getRecomendacao" + e.getMessage());
        }
         
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios1, uw);
            List<Estabelecimento> listaEstabelecimentosP = new ArrayList<Estabelecimento>();
            listaEstabelecimentosP.add(e2);
            Assert.assertEquals(recPer.getRecomendacao(5, listaTipos1, "---"),listaEstabelecimentosP);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 12 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios2, u1);
        	List<Estabelecimento> listaEstabelecimentosP1 = new ArrayList<Estabelecimento>();
        	Assert.assertEquals(recPer.getRecomendacao(3, listaTipos3, "---"),listaEstabelecimentosP1);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 13 de getRecomendacao" + e.getMessage());
        }
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios2, u2);
        	List<Estabelecimento> listaEstabelecimentosP1 = new ArrayList<Estabelecimento>();
        	listaEstabelecimentosP1.add(e3);
        	listaEstabelecimentosP1.add(e1);
        	Assert.assertEquals(recPer.getRecomendacao(3, listaTipos3, "---"),listaEstabelecimentosP1);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 14 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios2, u3);
        	List<Estabelecimento> listaEstabelecimentosP1 = new ArrayList<Estabelecimento>();
        	listaEstabelecimentosP1.add(e1);
        	Assert.assertEquals(recPer.getRecomendacao(3, listaTipos3, "---"),listaEstabelecimentosP1);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 15 de getRecomendacao" + e.getMessage());
        }
        
        try {
        	recPer = new RecomendacaoPersonalizada(listaUsuarios2, u4);
        	List<Estabelecimento> listaEstabelecimentosP1 = new ArrayList<Estabelecimento>();
        	listaEstabelecimentosP1.add(e1);
        	Assert.assertEquals(recPer.getRecomendacao(3, listaTipos3, "---"),listaEstabelecimentosP1);
        } catch(Exception e) {
            Assert.fail("Nao esperava erros no teste 16 de getRecomendacao" + e.getMessage());
        }
     }
}
